#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <imbus.h>

#define NO_TEST_OBJECT_MAIN
#include "test_object.h"
#include "test_object.c"

void print_value (IMValue *v)
{
    IMType type = IM_VALUE_TYPE (v);

    printf ("%s: ", im_type_get_name (type));

    switch (type) {
        case IM_TYPE_CHAR:
            printf ("Char %c\n", im_value_get_char (v));
            break;
        case IM_TYPE_UCHAR:
            printf ("UChar %c\n", im_value_get_uchar (v));
            break;
        case IM_TYPE_INT32:
            printf ("Int32 %d\n", im_value_get_int32 (v));
            break;
        case IM_TYPE_UINT32:
            printf ("UInt32 %u\n", im_value_get_uint32 (v));
            break;
        case IM_TYPE_INT64:
            printf ("Int64 %lld\n", im_value_get_int64 (v));
            break;
        case IM_TYPE_UINT64:
            printf ("UInt64 %llu\n", im_value_get_uint64 (v));
            break;
        case IM_TYPE_DOUBLE:
            printf ("Double %lf\n", im_value_get_double (v));
            break;
        case IM_TYPE_C_STRING:
            printf ("String %s\n", im_value_get_c_string (v));
            break;
        default:
            if (IM_TYPE_IS_OBJECT (im_value_get_value_type (v))) {
                if (type == IM_TYPE_VALUE) {
                    IMValue *obj = (IMValue*)im_value_get_object (v);
                    print_value (obj);
                } else
                    printf ("Object %s\n", im_type_get_name (im_value_get_value_type (v)));
            } else
                printf ("Unknown value type.\n");
            break;
        }
}

void for_each_array (IMPointer a, IMPointer u)
{
    IMValue *val = IM_VALUE(a);

    print_value (val);
}

void print_value_array (IMValueArray *a)
{
    printf ("sizeof (%s) = %d, has %d values\n",
            im_type_get_name (im_object_get_type (a)), 
            im_object_sizeof (a),
            im_value_array_size (a));

    printf ("All values:\n");

    im_value_array_foreach (a, for_each_array, 0);
}

int main (int argc, char *argv [])
{
    IMValueArray *a;
    Point        *p;

    im_init (&argc, &argv);

    TYPE_POINT;
    TYPE_CIRCLE;
#if IM_ENABLE_DEBUG
    _im_slice_print_debug_info ();
#endif

    a = im_value_array_new ();

    im_value_array_append (a, im_value_new_char ('a'));
    im_value_array_append (a, im_value_new_uchar ('A'));
    im_value_array_append (a, im_value_new_int16 (-16));
    im_value_array_append (a, im_value_new_uint16 (16));
    im_value_array_append (a, im_value_new_int32 (-32));
    im_value_array_append (a, im_value_new_uint32 (32));
    im_value_array_append (a, im_value_new_int64 (-64));
    im_value_array_append (a, im_value_new_int64 (-1234567890123LL));
    im_value_array_append (a, im_value_new_uint64 (1234567890123LL));
    im_value_array_append (a, im_value_new_double (1.2345));
    im_value_array_append (a, im_value_new_c_string ("Dyanmic string!"));
    im_value_array_append (a, im_value_new_static_c_string ("Static string!"));
    im_value_array_append (a, im_value_new_take_c_string (strdup ("Strdup string!")));

    p = (Point *) point_new (13, 21);
    im_value_array_append_object (a, p);

    p = (Point *) circle_new (15, 15, 20);
    im_value_array_append_object (a, p);

    im_value_array_append_object (a, im_value_new_double (3.1415926));
    im_value_array_append_object (a, im_value_new_static_c_string ("Nested string."));
    im_value_array_append_object (a, im_value_new_object (p));

    print_value_array (a);

    im_object_unref (a);

#if IM_ENABLE_DEBUG
    _im_slice_print_debug_info ();
#endif

    return 0;
}

/*
vi:ts=4:nowrap:ai:expandtab
*/
